
#include <string.h>
#include "../lib/data_list.h"

#define DATA_LEN_STORE_INDEX	(data_list->data_size-1)
#define DATA_HEAD_STORE_INDEX	(0)

uint8_t data_list_init(DATA_LIST_STRUCT* data_list,
					uint8_t* buffer, uint16_t buffer_len, uint8_t data_size)	//buffer_len = data_count_max*(data_size+1)
{
	if((data_list == 0)||(buffer == 0)||(buffer_len == 0)
		||(data_size == 0)||(data_size > buffer_len)){
		return 0;
	}

	buffer_len = buffer_len/(data_size+1);
	buffer_len = buffer_len*(data_size+1);

	data_list->data_list_buffer = buffer;
	data_list->data_list_len = buffer_len;
	data_list->data_size = data_size+1;

	memset(buffer, 0, buffer_len);

	return 1;
}

uint8_t* data_list_get_data_piont(DATA_LIST_STRUCT* data_list, uint16_t data_serial_num)	//data_serial_num:0~0xfffe
{
	if(data_list == 0){
		return 0;
	}

	if(data_serial_num >= data_list->data_list_len/data_list->data_size){
		return 0;
	}

	data_serial_num = data_serial_num*(data_list->data_size);

	return (uint8_t*)&(data_list->data_list_buffer[data_serial_num + DATA_HEAD_STORE_INDEX]);
}

uint8_t data_list_read_data(DATA_LIST_STRUCT* data_list,
							uint16_t data_serial_num, uint8_t* read_buffer, uint8_t* read_data_len)	//data_serial_num:0~0xfffe
{
	if((data_list == 0)||(read_buffer == 0)){
		return 0;
	}

	if(data_serial_num >= data_list->data_list_len/data_list->data_size){
		return 0;
	}

	data_serial_num = data_serial_num*(data_list->data_size);
	//read_p = data_serial_num;

	(*read_data_len) = data_list->data_list_buffer[data_serial_num + DATA_LEN_STORE_INDEX];
	if((*read_data_len) == 0){
		return 0;
	}
	if((*read_data_len) > (data_list->data_size)-1){
		(*read_data_len) = (data_list->data_size)-1;
	}
	memcpy(read_buffer, &(data_list->data_list_buffer[data_serial_num + DATA_HEAD_STORE_INDEX]),
			(*read_data_len));

	return 1;
}

uint8_t data_list_write_data(DATA_LIST_STRUCT* data_list,
							uint16_t data_serial_num, uint8_t* write_data, uint8_t write_data_len)	//data_serial_num:0~0xfffe, write_data_len <= data_size - 1
{
	if((data_list == 0)||(write_data == 0)){
		return 0;
	}

	if(write_data_len > (data_list->data_size)-1){
		return 0;
	}

	if(write_data_len == 0){
		return 0;
	}

	if(data_serial_num >= data_list->data_list_len/data_list->data_size){
		return 0;
	}

	data_serial_num = data_serial_num*(data_list->data_size);
	//write_p = data_serial_num;

	data_list->data_list_buffer[data_serial_num + DATA_LEN_STORE_INDEX] = write_data_len;
	memcpy(&(data_list->data_list_buffer[data_serial_num + DATA_HEAD_STORE_INDEX]), write_data,
			(write_data_len));

	return 1;
}

uint8_t data_list_del_data(DATA_LIST_STRUCT* data_list, uint16_t data_serial_num)	//data_serial_num:0~0xfffe
{
	if(data_list == 0){
		return 0;
	}

	if(data_serial_num >= data_list->data_list_len/data_list->data_size){
		return 0;
	}

	data_serial_num = data_serial_num*(data_list->data_size);
	//del_p = data_serial_num;

	if(data_list->data_list_buffer[data_serial_num + DATA_LEN_STORE_INDEX] == 0){
		return 0;
	}

	data_list->data_list_buffer[data_serial_num + DATA_LEN_STORE_INDEX] = 0;
	return 1;
}

uint8_t data_list_check_free_data(DATA_LIST_STRUCT* data_list, uint16_t data_serial_num)	//data_serial_num:0~0xfffe
{
	if(data_list == 0){
		return 0;
	}

	if(data_serial_num >= data_list->data_list_len/data_list->data_size){
		return 0;
	}

	data_serial_num = data_serial_num*(data_list->data_size);

	if(data_list->data_list_buffer[data_serial_num + DATA_LEN_STORE_INDEX] == 0){
		return 1;
	}
	else{
		return 0;
	}
}

uint16_t data_list_find_free_data(DATA_LIST_STRUCT* data_list)
{
	uint16_t data_serial_num;

	if(data_list == 0){
		return 0xffff;
	}

	data_serial_num = (data_list->data_list_len/data_list->data_size) - 1;
	while(1){
		if(data_list->data_list_buffer[data_serial_num*(data_list->data_size)
			 + DATA_LEN_STORE_INDEX] == 0){
			break;
		}
		if(data_serial_num == 0){
			data_serial_num = 0xffff;
			break;
		}
		data_serial_num--;
	}

	return data_serial_num;
}

uint16_t data_list_find_data(DATA_LIST_STRUCT* data_list, uint8_t compare_index,
								uint8_t* compare_data, uint8_t compare_data_len)
{
	uint16_t data_serial_num;
	uint16_t p;

	if(data_list == 0){
		return 0xffff;
	}

	if(compare_data == 0){
		return 0xffff;
	}

	if(compare_data_len > (data_list->data_size)-1){
		return 0xffff;
	}

	if(compare_data_len == 0){
		return 0xffff;
	}

	if(compare_index > (data_list->data_size)-1 - 1){
		return 0xffff;
	}

	data_serial_num = (data_list->data_list_len/data_list->data_size) - 1;
	while(1){
		p = data_serial_num*(data_list->data_size);
		if(data_list->data_list_buffer[p + DATA_LEN_STORE_INDEX] != 0){
			if(memcmp(&(data_list->data_list_buffer[p + DATA_HEAD_STORE_INDEX + compare_index]),
					compare_data, compare_data_len) == 0){
				break;
			}
		}
		if(data_serial_num == 0){
			data_serial_num = 0xffff;
			break;
		}
		data_serial_num--;
	}

	return data_serial_num;
}

uint8_t data_list_check_full(DATA_LIST_STRUCT* data_list)
{
	if(data_list_find_free_data(data_list) == 0xffff){
		return 1;
	}
	else{
		return 0;
	}
}

static uint16_t data_serial_num;
void data_list_find_data_continue_init(DATA_LIST_STRUCT* data_list)
{
    data_serial_num = (data_list->data_list_len/data_list->data_size) - 1;
}

uint16_t data_list_find_data_continue(DATA_LIST_STRUCT* data_list,
							uint8_t compare_index, uint8_t* compare_data, uint8_t compare_data_len)
{
	uint16_t p;

	if(data_list == 0){
		return 0xffff;
	}

	if(compare_data == 0){
		return 0xffff;
	}

	if(compare_data_len >(data_list->data_size)-1){
		return 0xffff;
	}

	if(compare_data_len == 0){
		return 0xffff;
	}

	if(compare_index == 0xff){
		return 0xffff;
	}

	while(1){
        p = data_serial_num*(data_list->data_size);
		if(data_list->data_list_buffer[p + DATA_LEN_STORE_INDEX] != 0){
			if(memcmp(&(data_list->data_list_buffer[p + compare_index]),
					compare_data, compare_data_len) == 0){
                data_serial_num--;
				break;
			}
		}
		if(data_serial_num == 0){
			data_serial_num = 0xffff;
			break;
		}
		data_serial_num--;
	}

    if(data_serial_num != 0xffff){
        return data_serial_num+1;
    }
    else{
        return data_serial_num;
    }
}

/*****************************************************
e.g.

DATA_LIST_STRUCT data_list_test;

typedef struct {
	uint8_t device_id;
	EmberEUI64 zigbee_mac;
	uint8_t end;
} END_DEVICE_STRUCT;

#define data_list_test_data_count_max 10
#define data_list_test_data_size (sizeof(END_DEVICE_STRUCT))
#define data_list_test_buff_len ((data_list_test_data_size+1)*data_list_test_data_count_max)
uint8_t data_list_test_buff[data_list_test_buff_len];

void print_data_list(void)
{
	uint8_t i;
	END_DEVICE_STRUCT* p;
	for(i = 0; i < data_list_test_data_count_max; i++){
		p = (END_DEVICE_STRUCT*)data_list_get_data_piont(&data_list_test, i);
		printf("%d:->%s\r\n",i, p->zigbee_mac);
	}
}

#include "stddef.h"
void test(void)
{
    uint8_t num;
    END_DEVICE_STRUCT temp;

	data_list_init(&data_list_test, data_list_test_buff, data_list_test_buff_len, data_list_test_data_size);
	print_data_list();

    num = 3;
    printf("data_list_write_data %d\r\n", num);
    memcpy(temp.zigbee_mac, "1122334455667789", EUI64_SIZE);
	data_list_write_data(&data_list_test, num, (uint8_t*)&temp, data_list_test_data_size);
	print_data_list();

	printf("data_list_check_free_data @ %d\r\n", num);
	num = data_list_check_free_data(&data_list_test, num);
	printf("data_list_check_free_data return:%d\r\n", num);

	num = data_list_find_data(&data_list_test, offsetof(END_DEVICE_STRUCT, zigbee_mac), "1122334455667789", EUI64_SIZE);
    printf("find @ :%d\r\n", num);

	num = data_list_find_data(&data_list_test, offsetof(END_DEVICE_STRUCT, zigbee_mac), "X12233445566778X", EUI64_SIZE);
    printf("find @ :%d\r\n", num);

    num = 3;
    printf("data_list_del_data @ %d\r\n", num);
 	data_list_del_data(&data_list_test, num);
	num = data_list_find_data(&data_list_test, offsetof(END_DEVICE_STRUCT, zigbee_mac), "1122334455667789", EUI64_SIZE);
    printf("find @ :%d\r\n", num);


    num = 1;
    printf("data_list_write_data %d\r\n", num);
    memcpy(temp.zigbee_mac, "X12233445566778X", EUI64_SIZE);
	data_list_write_data(&data_list_test, num, (uint8_t*)&temp, data_list_test_data_size);
	print_data_list();

    num = 5;
    printf("data_list_write_data %d\r\n", num);
    memcpy(temp.zigbee_mac, "X12233445566778X", EUI64_SIZE);
	data_list_write_data(&data_list_test, num, (uint8_t*)&temp, data_list_test_data_size);
	print_data_list();


	num = 9;
    printf("data_list_write_data %d\r\n", num);
    memcpy(temp.zigbee_mac, "X12233445566778X", EUI64_SIZE);
	data_list_write_data(&data_list_test, num, (uint8_t*)&temp, data_list_test_data_size);
	print_data_list();

    num = 0;
    data_list_find_data_continue_init(&data_list_test);
    printf("data_list_find_data_continue\r\n");
    while(num != 0xff){
        num = data_list_find_data_continue(&data_list_test, offsetof(END_DEVICE_STRUCT, zigbee_mac), "X12233445566778X", EUI64_SIZE);
        printf("find @ :%d\r\n", num);
    }
}

*************************************************************/
